1. Field of the Invention
The present invention relates generally to multithreaded processes, and more particularly, to serializing access to multithreading unsafe resources.
2. Description of the Related Art
Many of today's computer systems and operating systems permit multitasking which allows many programs (known as processes) to run concurrently even when the computer system has only a single central-processing-unit (CPU). An important feature of multitasking is that each process has its own address space. Most computer systems and operating systems that support multitasking also support multithreading. Threads are like processes, but each thread must be associated with a process. Hence, with multithreading, each process can include multiple threads which share the same address space and stack area.
Modern programs make use of multithreading when developing programs or code for execution on computer systems and operating systems which support multithreading. However, there exists a large body of libraries, databases, toolkits, algorithms or other resources which these multithreaded applications would like to access, but have difficulty doing so because the resources do not support multithreading. The difficulty arises from the fact that multithreaded accesses to such resources would be unsafe because the results could not be guaranteed to be correct. Resources that do not support multithreading are called multithreading unsafe resources.
Prior approaches have attempted to serialize the multithreaded accesses by placing all such accesses into a single thread prior to accessing resources which are multithreading unsafe. Typically, the accesses are system calls or function calls. One approach is to permit accesses to multithreaded unsafe resources only from a main thread, and restricting all other threads from accessing the multithreaded unsafe resources. This approach is unsatisfactory because it places a difficult burden on the programmer to insure that all calls are carried out from a main thread. Another known approach is to serialize access to the multithreading unsafe resources using MUTEX (mutually exclusive) semaphores. Serializing access to a resource means that only one thread at a time can access the resource. A MUTEX semaphore provides a locking scheme that locks the resource while a thread owns the resource. The lock insures that all other threads are locked out from the resource, that is, unable to access the resource. The MUTEX lock approach is further discussed in Effective Multithreading in OS/2, by Len Dorfman and Marc J. Neuberger, McGraw-Hill, 1994.
FIG. 1 illustrates an example of the difficulties associated with serializing access to a multithreading unsafe resource. A process 10 shown in FIG. 1 uses a MUTEX lock to implement the serialization. The process 10 executes in a single thread and includes function calls to unsafe Func.sub.-- x and unsafe Func.sub.-- y. Prior to executing unsafe function call Func.sub.-- x, an obtain lock command (obtainlock) is issued to obtain the MUTEX lock. The software developer places the obtain lock command in the code for the process so as to obtain the MUTEX lock for the resource which the process will soon call via unsafe Func.sub.-- x. However, in this example, following the unsafe function call (unsafe Func.sub.-- x), the function FOO is called, which in turns calls function BAR. The function BAR contains an unsafe function call (unsafe Func.sub.-- y). Hence, prior to the unsafe function call (unsafe Func.sub.-- y) within function BAR, the software developer would (assuming the developer knows of the unsafe function call with function BAR) place an obtain lock command (obtainlock) so as to obtain the MUTEX lock for the resource. However, since the FOO function obtained the MUTEX lock earlier and has not yet released the MUTEX lock, a deadlock condition results and the process cannot continue. The problem in this example is that the developer did not release the MUTEX lock before again seeking to obtain the lock. To insure proper execution in this example, the developer should have placed a release lock command (releaselock) after the unsafe function call (unsafe Func.sub.-- x) and before the function call to function FOO. The proper placement of the release lock command for this example is shown by reference number 12 in FIG. 1.
The problem with all of the prior approaches to serializing access to multithreading unsafe resources is that their implementations are very difficult. The burden on software developers to manage the serialization is too high. Further, the risk of mismanaging the serialization of the accesses can be disastrous, namely program crash or erroneous execution. In some cases, it is easier and less problematic to simply rewrite the code associated with the multithreading unsafe resources, than to implement one of the prior approaches.
Thus, there is a need for an improved technique to serialize access to multithreading unsafe resources which does not place a substantial burden on software developers.